package com.kryptnostic.kodex.v1.crypto.ciphers; import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidParameterSpecException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.kryptnostic.kodex.v1.constants.Names; import com.kryptnostic.kodex.v1.exceptions.types.SecurityConfigurationException; public abstract class AbstractCryptoService implements CryptoService { protected final Cypher cypher; protected static final int INTEGER_BYTES = Integer.SIZE / Byte.SIZE; public AbstractCryptoService( Cypher cypher ) { this.cypher = cypher; } /* * (non-Javadoc) * @see com.kryptnostic.kodex.v1.crypto.ciphers.CryptoService#encrypt(byte[]) */ @Override public BlockCiphertext encrypt( byte[] bytes ) throws SecurityConfigurationException { return encrypt( bytes, new byte[ 0 ] ); } /* * (non-Javadoc) * @see com.kryptnostic.kodex.v1.crypto.ciphers.CryptoService#encrypt(byte[], byte[]) */ @Override public BlockCiphertext encrypt( byte[] bytes, byte[] salt ) throws SecurityConfigurationException { try { SecretKeySpec secretKeySpec = getSecretKeySpec( salt ); Cipher cipher = cypher.getInstance(); byte[] iv; cipher.init( Cipher.ENCRYPT_MODE, secretKeySpec ); AlgorithmParameters params = cipher.getParameters(); if ( params == null ) { iv = Cyphers.generateSalt( cypher.getKeySize() >>> 3 ); try { cipher.init( Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec( iv ) ); } catch ( InvalidAlgorithmParameterException e ) { throw new SecurityConfigurationException( e ); } } else { iv = params.getParameterSpec( IvParameterSpec.class ).getIV(); } byte[] encryptedBytes = cipher.doFinal( bytes ); return new BlockCiphertext( iv, salt, encryptedBytes ); } catch ( NoSuchAlgorithmException e ) { throw new SecurityConfigurationException( e ); } catch ( InvalidKeySpecException e ) { throw new SecurityConfigurationException( e ); } catch ( IllegalBlockSizeException e ) { throw new SecurityConfigurationException( e ); } catch ( BadPaddingException e ) { throw new SecurityConfigurationException( e ); } catch ( NoSuchPaddingException e ) { throw new SecurityConfigurationException( e ); } catch ( InvalidKeyException e ) { throw new SecurityConfigurationException( e ); } catch ( InvalidParameterSpecException e ) { throw new SecurityConfigurationException( e ); } } /* * (non-Javadoc) * @see com.kryptnostic.kodex.v1.crypto.ciphers.CryptoService#decryptBytes(com.kryptnostic.kodex.v1.crypto.ciphers. * BlockCiphertext) */ @Override public byte[] decryptBytes( BlockCiphertext ciphertext ) throws SecurityConfigurationException { try { SecretKeySpec spec = getSecretKeySpec( ciphertext.getSalt() ); Cipher cipher = cypher.getInstance(); cipher.init( Cipher.DECRYPT_MODE, spec, new IvParameterSpec( ciphertext.getIv() ) ); return cipher.doFinal( ciphertext.getContents() ); } catch ( NoSuchAlgorithmException e ) { throw new SecurityConfigurationException( e ); } catch ( InvalidKeySpecException e ) { throw new SecurityConfigurationException( e ); } catch ( IllegalBlockSizeException e ) { throw new SecurityConfigurationException( e ); } catch ( BadPaddingException e ) { throw new SecurityConfigurationException( e ); } catch ( NoSuchPaddingException e ) { throw new SecurityConfigurationException( e ); } catch ( InvalidKeyException e ) { throw new SecurityConfigurationException( e ); } catch ( InvalidAlgorithmParameterException e ) { throw new SecurityConfigurationException( e ); } } /* * (non-Javadoc) * @see com.kryptnostic.kodex.v1.crypto.ciphers.CryptoService#getCypher() */ @Override @JsonProperty( Names.CYPHER_FIELD ) public Cypher getCypher() { return cypher; } @JsonIgnore protected abstract SecretKeySpec getSecretKeySpec( byte[] salt ) throws NoSuchAlgorithmException, InvalidKeySpecException; }